<template>
  <div class="GSAP">
    <canvas hidden id="hero-lightpass" />
    <div v-for="i in ballSize" :key="i" :class="`box box${i - 1}`" :style="{ top: `${10 * i}px` }">
    </div>
    <div class="w-[100px] absolute left-0 top-[200px]" hidden>
      <div class="w-[100px] h-[100px] bg-[#0f08] rounded-full flex items-center justify-center" id="green">green</div>
      <div class="w-[100px] h-[100px] bg-[#00f8] rounded-full flex items-center justify-center" id="blue">blue</div>
      <div class="w-[100px] h-[100px] bg-[#f008] rounded-full flex items-center justify-center" id="orange">orange</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger' // Import ScrollTrigger plugin
import { ref, onMounted, onUnmounted } from 'vue'
// 获取视口宽度
const viewportWidth = ref(0)
// 获取滚动条宽度
const scrollbarWidth = ref(0)
// 获取.box元素宽度
const boxWidth = ref(0)

// Register ScrollTrigger plugin
gsap.registerPlugin(ScrollTrigger)

// 窗口重置函数
const resetWindow = () => {
  viewportWidth.value = window.innerWidth;
  scrollbarWidth.value = window.innerWidth - document.documentElement.clientWidth;
  boxWidth.value = (document.querySelector(".box") as HTMLElement)?.offsetWidth || 0;
  boxMove();
}
const ballSize = 100;
const boxMove = () => {
  // 现有的.box元素左右移动动画
  const x = viewportWidth.value - scrollbarWidth.value - boxWidth.value;

  for (let i = 0; i < ballSize; i++) {
    gsap.to(`.box${i}`, {
      x: x,
      duration: 2,
      delay: i / 10,
      // ease: "power1.out",
      // ease: "power1.inOut",
      ease: "power2.inOut",
      // ease: "power3.inOut",
      // ease: "power4.inOut",
      // ease: "back.inOut",
      repeat: -1,
      yoyo: true
    });
  }
}
onMounted(() => {
  // 窗口重置
  window.addEventListener("resize", resetWindow);
  resetWindow();

  // 现有的timeline动画
  let tl = gsap.timeline({ delay: 1, repeat: -1, yoyo: true });
  tl.to("#green", { duration: 1, x: 786, rotation: 360 }, 0.5)
    .to("#blue", { duration: 1, x: 786, rotation: 360 }, '-=0.75')
    .to("#orange", { duration: 1, x: 786, rotation: 360 }, '+=1')

  const canvas = document.getElementById("hero-lightpass");
  const context = canvas instanceof HTMLCanvasElement ? canvas.getContext("2d") : null;

  if (canvas) {
    if (canvas instanceof HTMLCanvasElement) {
      canvas.width = 1158;
    }
    if (canvas instanceof HTMLCanvasElement) {
      canvas.height = 770;
    }
  }

  const frameCount = 147;
  const currentFrame = (index: number) => (
    `https://www.apple.com/105/media/us/airpods-pro/2019/1299e2f5_9206_4470_b28e_08307a42f19b/anim/sequence/large/01-hero-lightpass/${(index + 1).toString().padStart(4, '0')}.jpg`
  );

  const images: HTMLImageElement[] = []
  const airpods = {
    frame: 0
  };

  for (let i = 0; i < frameCount; i++) {
    const img = new Image();
    img.src = currentFrame(i);
    images.push(img);
  }

  gsap.to(airpods, {
    frame: frameCount - 1,
    snap: "frame",
    ease: "none",
    scrollTrigger: {
      scrub: 0.5
    },
    onUpdate: render
  });
  images[0].onload = render;

  function render() {
    context?.clearRect(0, 0, canvas instanceof HTMLCanvasElement ? canvas.width : 0, canvas instanceof HTMLCanvasElement ? canvas.height : 0);
    context?.drawImage(images[airpods.frame], 0, 0);
  }
})
onUnmounted(() => {
  // 移除窗口重置事件
  window.removeEventListener("resize", resetWindow);
})
</script>
<style scoped lang="scss">
.GSAP {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;

  .box {
    position: absolute;
    top: 100px;
    left: 0;
    width: 10px;
    height: 10px;
    background-image: radial-gradient(circle at 30% 30%, white, red, black);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 10px #000;
    text-shadow: 2px 2px 4px #fff0, -2px -2px 4px #0000;
  }

  canvas {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    max-width: 100vw;
    max-height: 100vh;
    object-fit: contain;
    mix-blend-mode: lighten;
  }
}
</style>
